package com.xinzhitong.www.provider;

import com.xinzhitong.www.enumeration.OrderType;
import org.apache.ibatis.jdbc.SQL;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * 条件搜索相关操作sql提供器
 *
 * @author 徐鑫
 */
@Component
public class SelectSQLProvider extends BaseSQLProvider {

    /**
     * 条件搜索及关键字搜索
     *
     * @param table        表名
     * @param selectFields 需要显示的字段名
     * @param keyWord      关键字
     * @param conditions   条件
     * @param orderField   排序字段
     * @param orderType    排序类型
     * @return 对应的sql语句
     */
    public String getSQLOfSelectByConditionsWithKeyWord(
            String table,
            String[] selectFields,
            String keyWord,
            Map<String, Object> conditions,
            String orderField,
            OrderType orderType
    ) {
        Set<String> min = new HashSet<>();
        Set<String> max = new HashSet<>();
        List<String> equalConditions = new ArrayList<>();

        //若条件为空
        if (conditions != null) {
            for (Map.Entry<String, Object> entry : conditions.entrySet()) {
                String key = entry.getKey();
                String prefix = key.substring(0, 3);
                //筛选范围条件
                if (prefix.equals("min") || prefix.equals("max")) {
                    //取出最小最大键
                    String minKey = "min" + key.substring(3);
                    String maxKey = "max" + key.substring(3);
                    min.add(minKey);
                    max.add(maxKey);
                } else
                    equalConditions.add(key);
            }
        }

        //整合为范围条件
        String[][] rangeConditions = new String[][]{
                min.toArray(new String[]{}),
                max.toArray(new String[]{})
        };

        SQL sql = new SQL();

        for (String str : selectFields)
            sql.SELECT(str);
        sql.FROM(table);


        boolean isFirst = true;
        //遍历等于条件
        for (String key : equalConditions) {
            String value;
            //尝试转化键对应的值
            try {
                value = sqlValueOf(conditions.get(key));
            } catch (NullPointerException e) {
                continue;
            }

            //添加条件
            if (isFirst) {
                isFirst = false;
                sql.WHERE(key + "=" + value);
            } else
                sql.AND().WHERE(key + "=" + value);
        }

        //遍历范围条件
        for (int i = 0; i < rangeConditions[0].length; i++) {
            //获取范围条件值
            String minKey = rangeConditions[0][i];
            String maxKey = rangeConditions[1][i];
            String key = minKey.substring(3);
            String minValue, maxValue;
            try {
                assert conditions != null;
                minValue = sqlValueOf(conditions.get(minKey));
            } catch (NullPointerException e) {
                minValue = null;
            }
            try {
                maxValue = sqlValueOf(conditions.get(maxKey));
            } catch (NullPointerException e) {
                maxValue = null;
            }

            //添加范围条件
            if (isFirst && minValue != null) {
                isFirst = false;
                sql.WHERE(minKey + ">=" + minValue);
            } else if (minValue != null)
                sql.AND().WHERE(minKey + ">=" + minValue);

            if (isFirst && maxValue != null) {
                isFirst = false;
                sql.WHERE(maxKey + "<=" + maxValue);
            } else if (maxValue != null)
                sql.AND().WHERE(maxKey + "<=" + maxValue);
        }

        //添加排序条件
        if (orderField != null) {
            sql.ORDER_BY(orderField + " " + orderType);
        }

        //添加关键字
        if (keyWord != null) {
            keyWord = sqlValueOf(keyWord);
            String fields = String.join(",", selectFields);
            if (isFirst) {
                sql.WHERE("concat(" + fields + ") like " + keyWord);
            } else {
                sql.AND().WHERE("concat(" + fields + ") like " + keyWord);
            }
            sql.ORDER_BY("length(concat(" + fields + "))");
        }

        System.out.println(sql.toString());
        return sql.toString();
    }

}
